package DAO;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import Pojo.Aluno;
import Pojo.Atividade;
import Pojo.HistoricoTurma;
import Pojo.Turma;

/** Classe HistoricoTurma
 * Essa classe implementa a interface HistoricoTurmaDao para comunicar com arquivo.
 * @author Ronan Lopes
 *
 */
public class HistoricoTurmaDaoImplArquivo implements HistoricoTurmaDao{
	
	/** Lista de HistoricoTurma.*/
	private List<HistoricoTurma> listaHistoricoTurmas;
	
	/** Atributo constante com o endereço do arquivo onde será armazenada os dados.*/
	private static final String nomeArquivo = "Arquivos/HistoricoTurmas.txt";
	
	/** Atributo onde é guardado o próximo id para inserção na lista.*/
	private int proximoId;
	
	/**
	 * Construtor da classe com um identificador indicando que não é necessário buscar dados do arquivo
	 * @param identificador
	 */
	public HistoricoTurmaDaoImplArquivo(int identificador){
		this.listaHistoricoTurmas = new ArrayList<HistoricoTurma>();
		this.proximoId=0;
	}
	
	/**
	 * Construtor da classe que busca dados no arquivo
	 */
	public HistoricoTurmaDaoImplArquivo(){
		this.listaHistoricoTurmas = new ArrayList<HistoricoTurma>();
		this.proximoId=0;
		this.buscarArmazenamento();
	}
	
	/**
	 * Getter do próximo id do HistoricoTurma
	 * @return próximo id disponível
	 */
	public int getProximoId(){
		return(this.proximoId);
	}
	
	/**
	 * Lista dos HistoricosTurma. 
	 * @return Lista dos HistoricoTurmas.
	 */
	public List<HistoricoTurma> getListaHistoricoTurmas(){
		return(this.listaHistoricoTurmas);
	}
	
	/**
	 * Busca Armazenamento no arquivo, trata os dados e monta a lista dos historicosTurma.
	 */
	private void buscarArmazenamento(){
		try{
			this.listaHistoricoTurmas = new ArrayList<HistoricoTurma>();
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    HistoricoTurma historicoTurma;
		    String dados[];
		    Aluno aluno;
		    Turma turma;
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	aluno = buscarAluno(Integer.parseInt(dados[4]));
		    	turma = buscarTurma(Integer.parseInt(dados[5]));
		    	historicoTurma = new HistoricoTurma(Integer.parseInt(dados[0]),Integer.parseInt(dados[1]),Double.parseDouble(dados[2]),Boolean.parseBoolean(dados[3]),aluno, turma);
		    	this.listaHistoricoTurmas.add(historicoTurma);
		    	linha = lerArq.readLine();						//Lê as linhas.
		    	this.proximoId=Integer.parseInt(dados[0]);
		    }
		    this.proximoId++;
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
	}
	
	/**
	 * Busca no armazenamento usando o id de uma turma. É usado para quando não se quer carregar os dados para a lista.
	 * @param idTurma
	 * @return Lista de HistóricoTurma
	 */
	public List<HistoricoTurma> buscarArmazenamentoPorTurma(int idTurma){
		
		List<HistoricoTurma> listaHistoricosTurma = new ArrayList<HistoricoTurma>();
		HistoricoTurma historicoTurma;
		
		try{
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    String dados[];
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	if (Integer.parseInt(dados[0])==idTurma){
		    		historicoTurma = new HistoricoTurma(Integer.parseInt(dados[0]),Integer.parseInt(dados[1]),Double.parseDouble(dados[2]),Boolean.parseBoolean(dados[3]));
		    		listaHistoricosTurma.add(historicoTurma);
		    	}
		    	linha = lerArq.readLine();						//Lê as linhas.
		    }
		    
		    arq.close();										//Fechando o arquivo
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
		return(listaHistoricosTurma);
	}
	
	/**
	 * Busca no armazenamento usando o id de um aluno. É usado para quando não se quer carregar os dados para a lista.
	 * @param idAluno
	 * @return Lista de HistóricoTurmas
	 */
	public List<HistoricoTurma> buscarArmazenamentoProcurarPorAluno(int idAluno){
		try{
			FileReader arq = new FileReader(nomeArquivo);		//Cria objeto arquivo
		    BufferedReader lerArq = new BufferedReader(arq);	//Cria objeto de leitura
		    String linha=lerArq.readLine();
		    HistoricoTurma historico;
		    String dados[];
		    List<HistoricoTurma> listaHistoricoTurma = new ArrayList<HistoricoTurma>();
		    
		    while (linha != null) {
		    	dados = linha.split("\t");
		    	if (Integer.parseInt(dados[4])==idAluno){
		    		historico = new HistoricoTurma(Integer.parseInt(dados[0]),Integer.parseInt(dados[1]),Double.parseDouble(dados[2]),Boolean.parseBoolean(dados[3]));
		    		listaHistoricoTurma.add(historico);
		    	}
		    	linha = lerArq.readLine();						//Lê as linhas.
		    }
		    arq.close();										//Fechando o arquivo
		    return(listaHistoricoTurma);
		}catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
		return(null);
	}
	
	/**
	 * Método usado para salvar a lista do arquivo. O arquivo é sobrescrito nesse método.
	 */
	private void salvarArmazenamento(){
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(nomeArquivo));
			Iterator<HistoricoTurma> i = listaHistoricoTurmas.iterator();
			
			HistoricoTurma historicoTurma;
			while(i.hasNext()){
				historicoTurma = (HistoricoTurma) i.next();
				out.write(historicoTurma.toString());
			}
			
			out.close();
		} catch (IOException e) {
			System.err.printf("Erro ao manipular o arquivo: %s.\n",e.getMessage());
		}
	}
	
	/**
	 * Método de adicionar o HistoricoTurma na lista. 
	 * É verificado se ele o código dele já existe, pois se existir não pode ser adicionado.
	 * Após inserir, o método "salvarArmazenamento()" é chamado
	 * @param historicoTurma
	 * @return true se foi possível inserir ou falso se ele foi encontrado na lista.
	 */
	public boolean adicionarHistoricoTurma(HistoricoTurma historicoTurma){
		Iterator<HistoricoTurma> i = listaHistoricoTurmas.iterator();
		HistoricoTurma historicoTurmaComparacao;
		while(i.hasNext()){
			historicoTurmaComparacao = (HistoricoTurma) i.next();
			if (historicoTurmaComparacao.getIdHistoricoTurma() == historicoTurma.getIdHistoricoTurma()){
				return(false);
			}
		}
		this.listaHistoricoTurmas.add(historicoTurma);
		this.proximoId++;
		this.salvarArmazenamento();
		return(true);
	}
	
	/**
	 * Método de remover o HistoricoTurma na lista. 
	 * Após inserir, o método "salvarArmazenamento()" é chamado
	 * @param historicoTurma
	 * @return true se o aluno foi encontrado na lista para ser removido ou false se ele não foi encontrado
	 */
	public boolean removerHistoricoTurma(HistoricoTurma historicoTurma){
		Iterator<HistoricoTurma> i = listaHistoricoTurmas.iterator();
		HistoricoTurma historicoTurmaComparacao;
		boolean resultado;
		while(i.hasNext()){
			historicoTurmaComparacao = (HistoricoTurma) i.next();
			if (historicoTurmaComparacao.getIdHistoricoTurma() == historicoTurma.getIdHistoricoTurma()){
				resultado = this.listaHistoricoTurmas.remove(historicoTurmaComparacao);
				this.salvarArmazenamento();
				return(resultado);
			}
		}
		return(false);
	}
	
	/**
	 * Verificação da existência de um históricoTurma pesquisando por um aluno e uma turma
	 * @param idAluno
	 * @param idTurma
	 * @return inteiro que referência o código do históricoTurma encontrado. Se não foi encontrado retorna a flag -1 
	 */
	public int verificarAlunoCadastradoTurma(int idAluno, int idTurma){
		Iterator<HistoricoTurma> i = this.listaHistoricoTurmas.iterator();
		HistoricoTurma historicoTurmaComparacao;
		while(i.hasNext()){
			historicoTurmaComparacao = (HistoricoTurma) i.next();
			if ((historicoTurmaComparacao.getAluno().getIdAluno() == idAluno)&&(historicoTurmaComparacao.getTurma().getIdTurma() == idTurma)){
				return(historicoTurmaComparacao.getIdHistoricoTurma());
			}
		}
		return(-1);
	}
	
	/**
	 * Pesquisa de Alunos passando a turma
	 * @param turma
	 * @return Lista de Alunos cujo historicoTurma pertence à turma
	 */
	public List<Aluno> pesquisarAlunosPorTurma(Turma turma){
		Iterator<HistoricoTurma> i = this.listaHistoricoTurmas.iterator();
		HistoricoTurma historicoTurmaComparacao;
		List<Aluno> listaAlunos = new ArrayList<Aluno>();
		while(i.hasNext()){
			historicoTurmaComparacao = (HistoricoTurma) i.next();
			if (historicoTurmaComparacao.getTurma().getIdTurma() == turma.getIdTurma()){
				listaAlunos.add(historicoTurmaComparacao.getAluno());
			}
		}
		return listaAlunos;
	}
	
	/**
	 * Método que buscar o historicoTurma passando um aluno e uma turma
	 * @param aluno
	 * @param turma
	 * @return HistoricoTurma ou null se não encontrar
	 */
	public HistoricoTurma procurarPorAlunoETurma(Aluno aluno, Turma turma){
		Iterator<HistoricoTurma> i = this.listaHistoricoTurmas.iterator();
		HistoricoTurma historicoTurmaComparacao;
		while(i.hasNext()){
			historicoTurmaComparacao = (HistoricoTurma) i.next();
			if ((historicoTurmaComparacao.getAluno().getIdAluno() == aluno.getIdAluno())&&(historicoTurmaComparacao.getTurma().getIdTurma()==turma.getIdTurma())){
				return(historicoTurmaComparacao);
			}
		}
		return (null);
	}
	
	/**
	 * Método que pesquisa históricosTurmas passando uma turma passada por parâmetro
	 * @param turma
	 * @return Lista de HistoricoTurma
	 */
	public List<HistoricoTurma> procurarPorTurma(Turma turma){
		Iterator<HistoricoTurma> i = this.listaHistoricoTurmas.iterator();
		HistoricoTurma historicoTurmaComparacao;
		List<HistoricoTurma> listaHistoricoTurma = new ArrayList<HistoricoTurma>();
		while(i.hasNext()){
			historicoTurmaComparacao = (HistoricoTurma) i.next();
			if ((historicoTurmaComparacao.getTurma().getIdTurma() == turma.getIdTurma())){
				listaHistoricoTurma.add(historicoTurmaComparacao);
			}
		}
		return (listaHistoricoTurma);
	}
		
	/**
	 * Método para buscar o Aluno que estão relacionado com HistóricoTurma
	 * @param idAluno
	 * @return Aluno
	 */
	private Aluno buscarAluno(int idAluno){
		AlunoDaoImplArquivo alunoDaoImplArquivo = new AlunoDaoImplArquivo(idAluno);
		return(alunoDaoImplArquivo.buscarArmazenamentoProcurarPorId(idAluno));
	}
	
	/**
	 * Método para buscar a Turma que estão relacionado com HistóricoTurma
	 * @param idTurma
	 * @return Turma
	 */
	private Turma buscarTurma(int idTurma){
		TurmaDaoImplArquivo turmaDaoImplArquivo = new TurmaDaoImplArquivo(idTurma);
		return(turmaDaoImplArquivo.buscarArmazenamentoProcurarPorId(idTurma));
	}
	
			
}
